package com.om.deadlock;

public class Philosopher {
    public static final int EAT_DEADLINE = 20;
    private int starvationTimer = 0;
    private boolean isAlive = true;
    private Fork leftFork;
    private Fork rightFork;
    private State state = State.THINKING;

    enum State {
        THINKING, WAITING, EATING
    }

    private void stillWaitingToEat() {
        if (--starvationTimer <= 0)
            die();
    }

    private void die() {
        System.out.printf("Dead: %d - state %s\n", myNumber, state.name());
        isAlive = false;
    }

    public Philosopher(Fork left, Fork right) {
        this.leftFork = left;
        this.rightFork = right;
    }

    static int threadNumber = 0;

    static synchronized int nextNumber() {
        return threadNumber++;
    }

    int myNumber;

    private class Runner implements Runnable {
        public Runner() {
            myNumber = nextNumber();
        }

        public void run() {
            startEating();
        }
    };

    public void eat() throws Exception {
        new Thread(new Runner()).start();
    }

    private synchronized void startEating() {
        state = State.WAITING;
        starvationTimer = EAT_DEADLINE;
        leftFork.grab();
        rightFork.grab();
        state = State.EATING;
    }

    private synchronized void doneEating() {
        leftFork.drop();
        rightFork.drop();
        state = State.THINKING;
    }

    public void tic() {
        switch (state) {
        case EATING:
            doneEating();
            break;
        case THINKING:
            break;
        case WAITING:
            stillWaitingToEat();
            break;
        }
    }

    public boolean isAlive() {
        return isAlive;
    }
}
